home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK2.toast / Development Kits (Disc 2) / QuickTime / Programming Stuff / Documentation / develop articles / develop Issue 17 / MultipleMovies / MyMultipleMoviesApp ƒ / MyApplication Shell (1.0).c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-26  |  22.5 KB  |  803 lines  |  [TEXT/KAHL]

  1. //--------------------------------------------------------------------------
  2. //
  3. //        MyApplication Shell.
  4. //            by John Wang
  5. //
  6. //        Description:    Shell.
  7. //
  8. //        Version:    1.0        09/07/93    Completed.
  9. //
  10. //--------------------------------------------------------------------------
  11.  
  12. //    #includes:
  13.  
  14. #include    <EPPC.h>            //    Need constants to resume/suspend.
  15. #include    <GestaltEqu.h>        //    Check for System 7.
  16. #include    <AppleEvents.h>        //    Core AppleEvents is implemented.
  17.  
  18. #include    "MyApplication Shell (1.0).h"
  19. #include    "MyApplication.h"
  20.  
  21. //--------------------------------------------------------------------------
  22.  
  23. //    Globals:
  24.  
  25. Boolean            gDoneFlag;            //    Set to TRUE if you want to Application to kindly quit.
  26. Boolean            gHasAppleEvents;    //    TRUE if Gestalt returns saying AppleEvents is available.
  27. short            gScrapCount;        //    Keep track of scrap count.
  28. OSType            gScrapType;            //    Needed to know what type scrap it is.
  29. Handle            gScrap;                //    Must keep a handle to the scrap for update events that
  30.                                     //    happen in the background.  The reason is that when the app
  31.                                     //    is in the background, it does not have access to GetScrap().
  32.  
  33. //--------------------------------------------------------------------------
  34.  
  35. //    main:
  36.  
  37. void main()
  38. {
  39.     EventRecord     myEvent;
  40.     long            yieldTime;
  41.     WindowPtr        foundWindow;
  42.     short            windowPart;
  43.     Boolean            isEvent;
  44.     GrafPtr            savePort;
  45.     GDHandle        saveGD;
  46.     PScrapStuff        myScrapStuff;
  47.  
  48.     //    Initialize here.  Set the yield time too.
  49.     MAS_initialize();
  50.     yieldTime = MyYieldTime(suspendResumeMessage);
  51.  
  52.     //    Event loop.
  53.     for (;;) {
  54.  
  55.         //    Get the event.
  56.         isEvent = WaitNextEvent(everyEvent, &myEvent, yieldTime, nil);
  57.  
  58.         //    Allow application specific event handling.  We have three cases:
  59.         //        MYEVENTDEF == 2: MyEvent gets called for each window.
  60.         //        MYEVENTDEF == 1: MyEvent gets once with window parameter = nil.
  61.         //        MYEVENTDEF == 0: MyEvent never gets called.
  62.         //    MyEvent returns TRUE to indicate that the event is handled and can be ignored.
  63.         //    As the safe thing to do, we always set the port if we know what window is being used.
  64.         #if MYEVENTDEF == 2
  65.             if (isEvent) {
  66.                 foundWindow = (WindowPtr) WindowList;
  67.                 while (foundWindow != nil) {
  68.                     if (IsMyWindow(foundWindow)) {
  69.                         GetPort(&savePort);
  70.                         saveGD = GetGDevice();
  71.                         SetPort(foundWindow);
  72.                         SetGDevice(GetMainDevice());
  73.                         if (MyEvent(foundWindow, &myEvent))
  74.                             isEvent = FALSE;
  75.                         SetPort(savePort);
  76.                         SetGDevice(saveGD);
  77.                     }
  78.                     foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  79.                 }
  80.             }
  81.         #elif MYEVENTDEF == 1
  82.             if (isEvent) {
  83.                 if (MyEvent(nil, &myEvent)) {
  84.                     isEvent = FALSE;
  85.                 }
  86.             }
  87.         #elif MYEVENTDEF == 0
  88.         #endif
  89.         
  90.         //    If the event is unhandled by app specific event handling, then we proceed.
  91.         if (isEvent) {
  92.             switch (myEvent.what) {
  93.  
  94.                 case mouseDown:
  95.                     //    Get current port and device.
  96.                     GetPort(&savePort);
  97.                     saveGD = GetGDevice();
  98.                     
  99.  
  100.                     //    Set the port and gdevice to the window if we own the window.
  101.                     //    We can then assume anytime the event occured in one of our windows,
  102.                     //       that the port and gdevice are set correctly.
  103.                     windowPart = FindWindow(myEvent.where, &foundWindow);
  104.                     if (IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow)) {
  105.                         SetPort(foundWindow);
  106.                         SetGDevice(GetMainDevice());
  107.                     }
  108.                     
  109.                     //    Handle the different mouse down events.
  110.                     switch (windowPart) {
  111.                         case inSysWindow:
  112.                             SystemClick(&myEvent, foundWindow);
  113.                             break;
  114.                         case inMenuBar:
  115.                             MAS_adjustMenus();
  116.                             MAS_doCommand(MenuSelect(myEvent.where));
  117.                             break;
  118.                         case inContent:
  119.                             //    If in the content area of application's window, then select
  120.                             //    the window and call app specific routine.
  121.                             if (IsMyWindow(foundWindow)) {
  122.                                 SelectWindow(foundWindow);
  123.                                 MyInContent(foundWindow, myEvent.where);
  124.                             } else if (IsMyClipWindow(foundWindow)) {
  125.                                 SelectWindow(foundWindow);
  126.                             }
  127.                             break;
  128.                         case inDrag:
  129.                             //    If dragging one of the application's windows, then handle it.
  130.                             //    However, if we are dragging a zoomed window, we
  131.                             //    must remember to save the new window location into the
  132.                             //    zoomed rect in the data handle.  Otherwise, the event
  133.                             //    manager will think that we are no longer zoomed.
  134.                             if (IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow)) {
  135.                                 WStateData    *zoomData;
  136.                                 Rect        windowRect;
  137.                                 
  138.                                 //    Get window location before drag.
  139.                                 MAS_GetGlobalWindow(foundWindow, &windowRect);
  140.                                 
  141.                                 //    Drag window.
  142.                                 DragWindow (foundWindow, myEvent.where, &qd.screenBits.bounds);
  143.  
  144.                                 //    If the windowRect in global coordinates matches the zoom rect,
  145.                                 //    then assume that we are dragging the zoomed window.  update
  146.                                 //    zoom rect.
  147.                                 zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  148.                                 if (EqualRect(&(zoomData->stdState), &windowRect)) {
  149.                                     MAS_GetGlobalWindow(foundWindow, &windowRect);
  150.                                     zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  151.                                     zoomData->stdState = windowRect;
  152.                                 }
  153.                             }
  154.                             break;
  155.                         case inGrow:
  156.                             //    If growing one of the application's windows, then handle it.
  157.                             //    This also includes the clip window.
  158.                             //    See inDrag for details.
  159.                             if (IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow)) {
  160.                                 WStateData    *zoomData;
  161.                                 Rect        windowRect;
  162.                                 Rect        tempRect;
  163.                                 long        tempLong;
  164.                                 Str255        tempStr;
  165.                                 
  166.                                 //    Get window location before drag.
  167.                                 MAS_GetGlobalWindow(foundWindow, &windowRect);
  168.                                 
  169.                                 //    Grow the window.
  170.                                 tempRect = qd.screenBits.bounds;
  171.                                 tempRect.left = tempRect.top = 50;
  172.                                 GetWTitle(foundWindow, tempStr);
  173.                                 tempRect.left = StringWidth(tempStr) + 50;
  174.                                 if (tempLong = GrowWindow(foundWindow, myEvent.where, &tempRect)) {
  175.                                     tempRect = foundWindow->portRect;
  176.                                     InvalRect(&tempRect);
  177.                                     EraseRect(&tempRect);
  178.                                     InvalRect(&tempRect);
  179.                                     SizeWindow(foundWindow, tempLong, tempLong >> 16, true);
  180.                                 }
  181.  
  182.                                 //    If the windowRect in global coordinates matches the zoom rect,
  183.                                 //    then assume that we are dragging the zoomed window.  update
  184.                                 //    zoom rect.
  185.                                 zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  186.                                 if (EqualRect(&(zoomData->stdState), &windowRect)) {
  187.                                     MAS_GetGlobalWindow(foundWindow, &windowRect);
  188.                                     zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  189.                                     zoomData->stdState = windowRect;
  190.                                 }
  191.                             }
  192.                             break;
  193.                         case inGoAway:
  194.                             //    Handle clicking on the go away.  If it is the clip window,
  195.                             //    then hide it.
  196.                             if (TrackGoAway (foundWindow, myEvent.where)) {
  197.                                 if (IsMyWindow(foundWindow)) {
  198.                                     BringToFront(foundWindow);
  199.                                     MyClose();
  200.                                 } else if (IsMyClipWindow(foundWindow)) {
  201.                                     SetItem(GetMHandle(MENU_EDITID), MENU_EDITSHOWCLIP, "\PShow Clipboard");
  202.                                     MAS_hideClip(foundWindow);
  203.                                 }
  204.                             }
  205.                             break;
  206.                         case inZoomIn:
  207.                         case inZoomOut:
  208.                             //    Zoom application window and the clip window.
  209.                             if (TrackBox(foundWindow, myEvent.where, windowPart)) {
  210.                                 if (IsMyWindow(foundWindow))
  211.                                     MyZoomWindow(foundWindow, windowPart == 8);
  212.                                 else if (IsMyClipWindow(foundWindow))
  213.                                     MAS_zoomClip(foundWindow, windowPart == 8);
  214.                                 ZoomWindow(foundWindow, windowPart, TRUE);
  215.                             }
  216.                             break;
  217.                             break;
  218.                         default:
  219.                             break;
  220.                     }
  221.                     
  222.                     //    Restore port and device.
  223.                     SetPort(savePort);
  224.                     SetGDevice(saveGD);
  225.                     
  226.                     break;
  227.                 case keyDown:
  228.                 case autoKey:
  229.                     if ( myEvent.modifiers & cmdKey ) {
  230.                         if ( myEvent.what == keyDown ) {
  231.                             MAS_adjustMenus();
  232.                             MAS_doCommand(MenuKey(myEvent.message & charCodeMask));
  233.                         }
  234.                     } else
  235.                         MyDoKeyDown(&myEvent);
  236.                     break;
  237.                 case updateEvt:
  238.                     //    Handle update events for window and clip window.
  239.                     foundWindow = (WindowPtr) myEvent.message;
  240.                     GetPort(&savePort);
  241.                     saveGD = GetGDevice();
  242.                     SetPort(foundWindow);
  243.                     SetGDevice(GetMainDevice());
  244.                     BeginUpdate(foundWindow);
  245.                     if (IsMyWindow(foundWindow))
  246.                         MyDraw(foundWindow);
  247.                     else if (IsMyClipWindow(foundWindow))
  248.                         MAS_drawClip(foundWindow);
  249.                     EndUpdate(foundWindow);
  250.                     SetPort(savePort);
  251.                     SetGDevice(saveGD);
  252.                     break;
  253.                 case diskEvt:
  254.                     //    This handles a bad disk.  Otherwise the disk will not eject.
  255.                     if (myEvent.message >> 16) {
  256.                         Point    tempPoint;
  257.                         tempPoint.v = 50; tempPoint.h = 50;
  258.                         DIBadMount(tempPoint, myEvent.message);
  259.                     }
  260.                     break;
  261.                 case activateEvt:
  262.                     break;
  263.                 case app4Evt:
  264.                     switch (myEvent.message >> 24) {
  265.                         case suspendResumeMessage:
  266.                             yieldTime = MyYieldTime(myEvent.message & 0x01);
  267.                             break;
  268.                         default:
  269.                             DebugStr("\PUnexpected suspend/resume message.");
  270.                     }
  271.                     break;
  272.                 case kHighLevelEvent:
  273.                     if (gHasAppleEvents)
  274.                         AEProcessAppleEvent(&myEvent);
  275.                 default:
  276.                     break;
  277.             }
  278.         }
  279.     
  280.         //    If DoneFlag set, then quit.
  281.         if (gDoneFlag)
  282.             MAS_finishup();
  283.  
  284.         //    Do Idle routine.
  285.         //        MYIDLEDEF == 2: MyEvent gets called for each window.
  286.         //        MYIDLEDEF == 1: MyEvent gets once with window parameter = nil.
  287.         //        MYIDLEDEF == 0: MyEvent never gets called.
  288.         //    As the safe thing to do, we always set the port if we know what window is being used.
  289.         #if MYIDLEDEF == 2
  290.             foundWindow = (WindowPtr) WindowList;
  291.             while (foundWindow != nil) {
  292.                 if (IsMyWindow(foundWindow)) {
  293.                     GetPort(&savePort);
  294.                     saveGD = GetGDevice();
  295.                     SetPort(foundWindow);
  296.                     SetGDevice(GetMainDevice());
  297.                     MyIdle(foundWindow);
  298.                     SetPort(savePort);
  299.                     SetGDevice(saveGD);
  300.                 }
  301.                 foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  302.             }
  303.         #elif MYIDLEDEF == 1
  304.             MyIdle(nil);
  305.         #elif MYIDLEDEF == 0
  306.         #endif
  307.  
  308.         //    See if scrap changed.  If so, redraw if the clip window is found.
  309.         myScrapStuff = InfoScrap();
  310.         if (gScrapCount != myScrapStuff->scrapCount) {
  311.             foundWindow = (WindowPtr) WindowList;
  312.             while (foundWindow != nil) {
  313.                 if (IsMyClipWindow(foundWindow)) {
  314.                     GetPort(&savePort);
  315.                     saveGD = GetGDevice();
  316.                     SetPort(foundWindow);
  317.                     SetGDevice(GetMainDevice());
  318.                     MAS_drawClip(foundWindow);
  319.                     SetPort(savePort);
  320.                     SetGDevice(saveGD);
  321.                 }
  322.                 foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  323.             }
  324.         }
  325.     }
  326. }
  327.  
  328. //--------------------------------------------------------------------------
  329.  
  330. //    MyApplication Shell support routines (MAS_initialize, MAS_doCommand, and MAS_finishup):
  331.  
  332. void MAS_initialize()
  333. {
  334.     OSErr                err;
  335.     long                vers;
  336.     Handle                myMenu;
  337.     
  338.     //    Initialize Managaer.
  339.     MaxApplZone();
  340.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  341.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  342.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  343.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  344.     InitGraf(&qd.thePort);
  345.     FlushEvents(everyEvent, 0);
  346.     InitWindows();
  347.     InitDialogs(nil);
  348.     InitCursor();
  349.  
  350.     //    Set up menus.
  351.     myMenu = GetNewMBar(MENUBAR);
  352.     SetMenuBar(myMenu);
  353.     DisposHandle(myMenu);
  354.     AddResMenu(GetMHandle(MENU_APPLEID), 'DRVR');
  355.     DrawMenuBar();
  356.     
  357.     //    Require at least System 7.0.  We don't really need to be strict about this.
  358.     //    So, this can be removed if necessary.  But, test thoroughly with System 6 if you do.
  359.     Gestalt(gestaltSystemVersion, &vers);
  360.     vers = (vers >> 8) & 0x0f;
  361.     if (vers < 7) {
  362.         MAS_ReportError("\PThis Application does not run under System 6!", -1);
  363.         ExitToShell();
  364.     }
  365.     
  366.     //    Initialize AppleEvents if available.
  367.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &vers) == noErr);
  368.     if (gHasAppleEvents) {
  369.         err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, AEOpenHandler, 0, FALSE);
  370.         if (err) {
  371.             MAS_ReportError("\PError installing AppleEvent handlers.", err);
  372.             ExitToShell();
  373.         }
  374.         err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler, 0, FALSE);
  375.         if (err) {
  376.             MAS_ReportError("\PError installing AppleEvent handlers.", err);
  377.             ExitToShell();
  378.         }
  379.         err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, AEQuitHandler, 0, FALSE);
  380.         if (err) {
  381.             MAS_ReportError("\PError installing AppleEvent handlers.", err);
  382.             ExitToShell();
  383.         }
  384.         err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, AEPrintHandler, 0, FALSE);
  385.         if (err) {
  386.             MAS_ReportError("\PError installing AppleEvent handlers.", err);
  387.             ExitToShell();
  388.         }
  389.     }
  390.     
  391.     //    Setup other globals.
  392.     gDoneFlag = FALSE;
  393.  
  394.     //    Call app specific Intialization.
  395.     if (MAS_ReportError("\PError returned from MyInitialize:", MyInitialize()))
  396.         ExitToShell();
  397. }
  398.  
  399. void MAS_doCommand(long mResult)
  400. {
  401.     short             theMenu, theItem;
  402.     Str255            myStr;
  403.     GrafPtr            savePort;
  404.     GDHandle        saveGD;
  405.     WindowPtr        foundWindow;
  406.     
  407.     theItem = LoWord(mResult);
  408.     theMenu = HiWord(mResult);
  409.     
  410.     if (theItem != 0 || theMenu != 0) {
  411.         switch (theMenu) {
  412.             case MENU_APPLEID:
  413.                 if (theItem == 1) {
  414.                     ParamText(gMyAboutTitle, gMyAboutDesc, nil, nil);
  415.                     Alert(ALERT_ABOUT, nil);
  416.                 } else {
  417.                     GetItem(GetMHandle(MENU_APPLEID), theItem, myStr);
  418.                     GetPort(&savePort);
  419.                     saveGD = GetGDevice();
  420.                     (void) OpenDeskAcc(myStr);
  421.                     SetPort(savePort);
  422.                     SetGDevice(saveGD);
  423.                 }
  424.                 break;
  425.     
  426.             case MENU_FILEID:
  427.                 switch (theItem) {
  428.                     case MENU_FILENEW:
  429.                         MyNew();
  430.                         break;
  431.                     case MENU_FILEOPEN:
  432.                         MyOpen(nil);
  433.                         break;
  434.                     case MENU_FILECLOSE:
  435.                         if (IsMyClipWindow(FrontWindow())) {
  436.                             SetItem(GetMHandle(MENU_EDITID), MENU_EDITSHOWCLIP, "\PShow Clipboard");
  437.                             MAS_hideClip(FrontWindow());
  438.                         } else if (IsMyWindow(FrontWindow()))
  439.                             MyClose();
  440.                         else
  441.                             SysBeep(50);
  442.                         break;
  443.                     case MENU_FILESAVE:
  444.                         if (IsMyWindow(FrontWindow()))
  445.                             MySave();
  446.                         else
  447.                             SysBeep(50);
  448.                         break;
  449.                     case MENU_FILESAVEAS:
  450.                         if (IsMyWindow(FrontWindow()))
  451.                             MySaveAs();
  452.                         else
  453.                             SysBeep(50);
  454.                         break;
  455.                     case MENU_FILEPAGESETUP:
  456.                         if (IsMyWindow(FrontWindow()))
  457.                             MyPageSetup();
  458.                         else
  459.                             SysBeep(50);
  460.                         break;
  461.                     case MENU_FILEPRINT:
  462.                         if (IsMyWindow(FrontWindow()))
  463.                             MyPrint();
  464.                         else
  465.                             SysBeep(50);
  466.                         break;
  467.                     case MENU_FILEQUIT:
  468.                         gDoneFlag = TRUE;
  469.                         break;
  470.                     default:
  471.                         if (MAS_ReportError("\PError in handling file menu:", theItem))
  472.                             ExitToShell();
  473.                 }
  474.                 break;
  475.     
  476.             case MENU_EDITID:
  477.                 switch (theItem) {
  478.                     case MENU_EDITUNDO:
  479.                         MyUndo();
  480.                         break;
  481.                     case MENU_EDITCUT:
  482.                         MyCut();
  483.                         break;
  484.                     case MENU_EDITCOPY:
  485.                         MyCopy();
  486.                         break;
  487.                     case MENU_EDITPASTE:
  488.                         MyPaste();
  489.                         break;
  490.                     case MENU_EDITCLEAR:
  491.                         MyClear();
  492.                         break;
  493.                     case MENU_EDITSELECTALL:
  494.                         MySelectAll();
  495.                         break;
  496.                     case MENU_EDITSHOWCLIP:
  497.                         GetItem(GetMHandle(MENU_EDITID), MENU_EDITSHOWCLIP, myStr);
  498.                         if (myStr[1] == 'S') {        //    Obviously not very internationalizeable.
  499.                             MAS_showClip();
  500.                             SetItem(GetMHandle(MENU_EDITID), MENU_EDITSHOWCLIP, "\PHide Clipboard");
  501.                         } else {
  502.                             foundWindow = (WindowPtr) WindowList;
  503.                             while (foundWindow != nil) {
  504.                                 if (IsMyClipWindow(foundWindow)) {
  505.                                     SetItem(GetMHandle(MENU_EDITID), MENU_EDITSHOWCLIP, "\PShow Clipboard");
  506.                                     MAS_hideClip(foundWindow);
  507.                                 }
  508.                                 foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  509.                             }
  510.                         }
  511.                         break;
  512.                     default:
  513.                         if (MAS_ReportError("\PError in handling edit menu:", theItem))
  514.                             ExitToShell();
  515.                 }
  516.                 break;
  517.  
  518.             default:
  519.                 //    If not handled above, then allow app specific handling to occur.
  520.                 if (MAS_ReportError("\PError returned from MyDoCommand:", MyDoCommand(theMenu, theItem)))
  521.                     ExitToShell();
  522.         }
  523.     }
  524.     HiliteMenu(0);
  525.     return;
  526. }
  527.  
  528. void MAS_adjustMenus()
  529. {
  530.     MenuHandle        mHandle;
  531.     
  532.     if (IsMyClipWindow(FrontWindow())) {
  533.         mHandle = GetMHandle(MENU_FILEID);
  534.         DisableItem(mHandle, MENU_FILESAVE);
  535.         DisableItem(mHandle, MENU_FILESAVEAS);
  536.         DisableItem(mHandle, MENU_FILEPAGESETUP);
  537.         DisableItem(mHandle, MENU_FILEPRINT);
  538.         mHandle = GetMHandle(MENU_EDITID);
  539.         DisableItem(mHandle, MENU_EDITUNDO);
  540.         DisableItem(mHandle, MENU_EDITCUT);
  541.         DisableItem(mHandle, MENU_EDITCOPY);
  542.         DisableItem(mHandle, MENU_EDITPASTE);
  543.         DisableItem(mHandle, MENU_EDITCLEAR);
  544.         DisableItem(mHandle, MENU_EDITSELECTALL);
  545.     } else {
  546.         mHandle = GetMHandle(MENU_FILEID);
  547.         if (IsMyWindow(FrontWindow())) {
  548.             EnableItem(mHandle, MENU_FILESAVE);
  549.             EnableItem(mHandle, MENU_FILESAVEAS);
  550.             EnableItem(mHandle, MENU_FILEPAGESETUP);
  551.             EnableItem(mHandle, MENU_FILEPRINT);
  552.         } else {
  553.             DisableItem(mHandle, MENU_FILESAVE);
  554.             DisableItem(mHandle, MENU_FILESAVEAS);
  555.             DisableItem(mHandle, MENU_FILEPAGESETUP);
  556.             DisableItem(mHandle, MENU_FILEPRINT);
  557.         }
  558.         mHandle = GetMHandle(MENU_EDITID);
  559.         EnableItem(mHandle, MENU_EDITUNDO);
  560.         EnableItem(mHandle, MENU_EDITCUT);
  561.         EnableItem(mHandle, MENU_EDITCOPY);
  562.         EnableItem(mHandle, MENU_EDITPASTE);
  563.         EnableItem(mHandle, MENU_EDITCLEAR);
  564.         EnableItem(mHandle, MENU_EDITSELECTALL);
  565.     }
  566.     
  567.     MyAdjustMenus();
  568. }
  569.  
  570. void MAS_finishup()
  571. {
  572.     WindowPtr        frontWindow, nxtWindow;
  573.     
  574.     frontWindow = FrontWindow();
  575.     while (frontWindow != nil) {
  576.         nxtWindow = (WindowPtr) ((WindowPeek)frontWindow)->nextWindow;
  577.         if (IsMyClipWindow(frontWindow)) {
  578.             MAS_hideClip(frontWindow);
  579.         }
  580.         frontWindow = nxtWindow;
  581.     }
  582.     
  583.     //    Cleanup app specific stuff since all of the shell handles will be disposed of
  584.     //    when the heap disappears...
  585.     MyFinishup();
  586.  
  587.     //    Finally, quit app.
  588.     ExitToShell();
  589. }
  590.  
  591. //--------------------------------------------------------------------------
  592.  
  593. //    Clip Window support (MAS_showClip, MAS_drawClip, MAS_hideClip, and MAS_zoomClip):
  594.  
  595. void MAS_showClip()
  596. {
  597.     WindowPtr    myWindow;
  598.     Rect        clipBounds;
  599.     
  600.     myWindow = (WindowPtr) WindowList;
  601.     while (myWindow != nil) {
  602.         if (IsMyClipWindow(myWindow)) {
  603.             return;
  604.         }
  605.         myWindow = (WindowPtr) ((CWindowPeek) myWindow)->nextWindow;
  606.     }
  607.     
  608.     SetRect(&clipBounds, 10, 400, 510, 480);    
  609.     myWindow = NewCWindow(0L, &clipBounds, "\PClipboard", TRUE, zoomDocProc, (WindowPtr) -1, TRUE, 0L);
  610.     SetMyClipWindow(myWindow);
  611.     SetPort(myWindow);
  612.  
  613.     gScrapCount = 0;
  614.     gScrapType = 'NONE';    
  615.     if ((gScrap = NewHandle(0)) == nil) {
  616.         MAS_ReportError("\PCould not create handle for scrap storage:", -1);
  617.         ExitToShell();
  618.     }
  619. }
  620.  
  621. void MAS_drawClip(WindowPtr clipWindow)
  622. {
  623.     PScrapStuff    myScrapStuff;
  624.     long        scrapOffset, scrapLength;
  625.     Rect        myFrame;
  626.     Str255        myStr;
  627.     short        moveSize;
  628.     
  629.     //    See if scrap changed.
  630.     myScrapStuff = InfoScrap();
  631.     if (gScrapCount != myScrapStuff->scrapCount) {
  632.         gScrapCount = myScrapStuff->scrapCount;
  633.         if ((scrapLength = GetScrap(gScrap, 'PICT', &scrapOffset)) > 0) {
  634.             gScrapType = 'PICT';    
  635.         } else if ((scrapLength = GetScrap(gScrap, 'TEXT', &scrapOffset)) > 0) {
  636.             gScrapType = 'TEXT';    
  637.         } else
  638.             gScrapType = 'NONE';    
  639.     }
  640.  
  641.     //    Erase the window.
  642.     EraseRect(&(clipWindow->portRect));
  643.  
  644.     //    Draw something
  645.     if (gScrapType == 'PICT') {
  646.         myFrame = (**(PicHandle) gScrap).picFrame;
  647.         SetWTitle(clipWindow, "\PClipboard contents: picture");
  648.         DrawPicture((PicHandle) gScrap, &myFrame);
  649.  
  650.     } else if (gScrapType == 'TEXT') {
  651.         SetWTitle(clipWindow, "\PClipboard contents: text");
  652.         moveSize = GetHandleSize(gScrap);
  653.         if (moveSize > 255)
  654.             moveSize = 255;
  655.         BlockMove(*gScrap, myStr+1, moveSize);
  656.         myStr[0] = moveSize;
  657.         MoveTo(10, 40);
  658.         DrawString(myStr);
  659.     } else
  660.         SetWTitle(clipWindow, "\PNo PICT or TEXT to display.");
  661. }
  662.  
  663. void MAS_hideClip(WindowPtr clipWindow)
  664. {
  665.     DisposeWindow(clipWindow);
  666.     gScrapCount = 0;
  667.     gScrapType = 'NONE';
  668.     DisposeHandle(gScrap);
  669. }
  670.  
  671. void MAS_zoomClip(WindowPtr clipWindow, Boolean zoomOut)
  672. {
  673.     WStateData    *zoomData;
  674.     
  675.     //    IMPORTANT: Must not change stdState if not zooming out.  Otherwise, it will fool
  676.     //    the WDEF into thinking that it is not zoomed out when it really is.
  677.     
  678.     //    Don't call anything else since zoomData handle is not locked.
  679.     zoomData = (WStateData *) *(((CWindowPeek) clipWindow)->dataHandle);
  680.     
  681.     if (gScrapType == 'PICT') {
  682.         if (zoomOut) {
  683.             (zoomData->stdState).right = (zoomData->stdState).left +
  684.                                             ((**(PicHandle) gScrap).picFrame).right;
  685.             (zoomData->stdState).bottom = (zoomData->stdState).top +
  686.                                             ((**(PicHandle) gScrap).picFrame).bottom;
  687.         }
  688.     } else if (gScrapType == 'TEXT') {
  689.         if (zoomOut) {
  690.             (zoomData->stdState).right = (zoomData->stdState).left + 620;
  691.         }    
  692.     }
  693. }
  694.  
  695. //--------------------------------------------------------------------------
  696.  
  697. //    Shell utilities (MAS_ReportError, and MAS_GetGlobalWindow):
  698.  
  699. //    Show Alert.  Then, return true is err != noErr.
  700. Boolean MAS_ReportError(Str255 procStr, OSErr err)
  701. {
  702.     long    longerr = err;
  703.     Str255    myStr;
  704.     
  705.     if (longerr) {
  706.         NumToString(longerr, myStr);
  707.         ParamText("\PFATAL ERROR", procStr, myStr, nil);
  708.         Alert(ALERT_ERROR, nil);
  709.         return(TRUE);
  710.     } else
  711.         return(FALSE);
  712. }
  713.  
  714. void MAS_GetGlobalWindow(WindowPtr theWindow, Rect *windowRect)
  715. {
  716.     //    Get the windowRect in global coordinates.
  717.     *windowRect = theWindow->portRect;
  718.     LocalToGlobal(&topLeft(*windowRect));
  719.     LocalToGlobal(&botRight(*windowRect));
  720. }
  721.  
  722. //--------------------------------------------------------------------------
  723.  
  724. //    AppleEvents handling (AEOpenHandler, AEOpenDocHandler, AEPrintHandler,
  725. //       and AECloseHandler) :
  726.  
  727. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  728. {
  729.     //    We don't do anything more than simply call MyNew().
  730.     //    Thus, when app is opened from finder, MyNew will be called because the Finder
  731.     //    will send an open app AppleEvent message.
  732.     if (NEWDOCATSTARTUP)
  733.         MyNew();
  734.     
  735.     return(noErr);
  736. }
  737.  
  738. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  739. {
  740.     OSErr            err;
  741.     AEDescList        docList;
  742.     long            numItems;
  743.     FSSpec            myFSS;
  744.     Size            actualSize;
  745.     long            i;
  746.     DescType        typeCode;
  747.     AEKeyword        theKeyword;
  748.     
  749.     if (err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &docList))
  750.         return(err);
  751.     
  752.     if (err = AECountItems(&docList, &numItems))
  753.         return(err);
  754.         
  755.     for (i=1; i<=numItems; i++) {
  756.         if (err = AEGetNthPtr(&docList, i, typeFSS, &theKeyword, &typeCode, (Ptr) &myFSS,
  757.                     sizeof(FSSpec), &actualSize))
  758.             return(err);
  759.         
  760.         MyOpen(&myFSS);
  761.     }
  762.     
  763.     return(noErr);
  764. }
  765.  
  766. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  767. {
  768.     OSErr            err;
  769.     AEDescList        docList;
  770.     long            numItems;
  771.     FSSpec            myFSS;
  772.     Size            actualSize;
  773.     long            i;
  774.     DescType        typeCode;
  775.     AEKeyword        theKeyword;
  776.     
  777.     if (err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &docList))
  778.         return(err);
  779.     
  780.     if (err = AECountItems(&docList, &numItems))
  781.         return(err);
  782.     
  783.     for (i=1; i<=numItems; i++) {
  784.         if (err = AEGetNthPtr(&docList, i, typeFSS, &theKeyword, &typeCode, (Ptr) &myFSS,
  785.                     sizeof(FSSpec), &actualSize))
  786.             return(err);
  787.         
  788.         //    Open each file.  Print it.  Then close it.  MyOpen must make window frontmost.
  789.         MyOpen(&myFSS);
  790.         MyPrint();
  791.         MyClose();
  792.     }
  793.     
  794.     return(noErr);
  795. }
  796.  
  797. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  798. {
  799.     gDoneFlag = TRUE;
  800.     
  801.     return(noErr);
  802. }
  803.